<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body></body>
  <script>
    let PENDING = 'pending'
    let FULFILLED = 'fulfilled'
    let REJECTED = 'rejected'

    class MyPromise {
      constructor(cb) {
        cb(this.resolve, this.reject)
      }
      value = null
      errReason = null
      status = PENDING
      onFulfilledList = []
      onRejectedList = []
      resolve = (val) => {
        if (this.status === PENDING) {
          this.status = FULFILLED
          this.value = val
          while (this.onFulfilledList.length > 0) {
            this.onFulfilledList.shift()(this.value)
          }
        }
      }
      reject = (err) => {
        if (this.status === PENDING) {
          this.status = REJECTED
          this.errReason = err
          while (this.onRejectedList.length > 0) {
            this.onRejectedList.shift()(this.errReason)
          }
        }
      }
      then = (onFulfilled, onRejected) => {
        if (this.status === PENDING) {
          this.onFulfilledList.push(onFulfilled)
          this.onRejectedList.push(onRejected)
        } else if (this.status === FULFILLED) {
          onFulfilled(this.value)
        } else if (this.status === REJECTED) {
          onRejected(this.errReason)
        }
      }
      then2 = (onFulfilled, onRejected) => {
        const promise2 = new MyPromise((resolve, reject) => {
          if (this.status === FULFILLED) {
            queueMicrotask(() => {
              let res = onFulfilled(this.value)
              resolvePromise(promise2, res, resolve, reject)
            })
          } else if (this.status === REJECTED) {
            onRejected(this.errReason)
          } else if (this.status === PENDING) {
            this.onFulfilledList.push(onFulfilled)
            this.onRejectedList.push(onRejected)
          }
        })
        return promise2
      }
    }
    function resolvePromise(p, res, resolve, reject) {
      if (p === res) {
        return new Error()
      }
      if (res instanceof MyPromise) {
        res.then(resolve, reject)
      } else {
        resolve(res)
      }
    }
  </script>
</html>
